package library.GameLoader
{
	import Engine.Manager.EngineManager;
	
	import com.greensock.events.LoaderEvent;
	import com.greensock.loading.BinaryDataLoader;
	import com.greensock.loading.ImageLoader;
	import com.greensock.loading.LoaderMax;
	import com.greensock.loading.MP3Loader;
	import com.greensock.loading.XMLLoader;
	import com.greensock.loading.core.LoaderItem;
	
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	
	import library.GameLoader.ISWFLoader;
	
	import nochump.util.zip.ZipEntry;
	import nochump.util.zip.ZipFile;

	public class LoaderMain
	{
		
		
		//缓存相关回调函数
		public static var getShareObjectData:Function = null;
		public static var preCheckShareObjectSaveState:Function = null;
		public static var saveShareObjectData:Function = null;
		public static var checkSharedObjectSaveState:Function = null;
		
		public static const LOAD_TYPE_SWF:int = 1;		//SWF
		public static const LOAD_TYPE_TEXT:int = 2;		//文本
		public static const LOAD_TYPE_MAGIC:int = 3;		//图片
		public static const LOAD_TYPE_AS3XLS:int = 4;	
		public static const LOAD_TYPE_XML:int = 5;		//XML文件
		public static const LOAD_TYPE_SOUND:int = 6;		//声音
		public static const LOAD_TYPE_PACKAGE:int = 7;	//打包文件
		
		private static const VERSION_NO:String = "0";
		private static const BYTE_STATE_SINGLE_WEB:int = 1;	//单个文件的网络加载处理
		private static const BYTE_STATE_SINGLE_SHARE:int = 2;	//单个文件的本地加载处理
		private static const BYTE_STATE_ARRAY_WEB:int = 3;	//多个文件的网络加载处理
		private static const BYTE_STATE_ARRAY_SHARE:int = 4;	//多个文件的本络加载处理
		
		
		private var _loaderQueue:LoaderMax = null; 	//队列加载中心 参考库(greensock.LoaderMax)
		
		private var _loaderQueueCompuleteFun:Function = null;	//阵列加载完回调
		private var _loaderQueueProgressFun:Function = null;
		private var _loaderQueuePathList:Array = null;
		private var _loaderQueueReturnList:Array = null;
		
		private var _loaderSingleProgressFun:Function = null;
		
		private var _loaderArgDict:Object = {};	//单个加载数据保存
		private var _cookieDict:Object = {};		//保存加载缓存
		
		private var _loaderTempRetunList:Array = null;
		
		
		//加载进度计算相关
		private var _everyPross:Number = 0; //单个占的比率
		private var _webPross:Number = 0;	  //网络部分所占比率
		private var _sharePross:Number = 0;//本地部分所占比率
		
		private var _versionTxt:String = VERSION_NO;
		private var _clientIP:String = "";
		
		
		public function LoaderMain()
		{
			_loaderArgDict = {};
			_loaderQueue = new LoaderMax({name:"mainQueue", onProgress:progressHandlerQueue, onComplete:completeHandlerQueue, onError:errorHandlerQueue});
		}
		
		public function loadURLResVersion(version:String, ip:String, onLoadComplete:Function):void
		{
			if (version == null || version == "" || (!version))
				_versionTxt = VERSION_NO;
			else
				_versionTxt = version+ "_V";
			
			if (ip == null || ip == "" || (!ip))
				_clientIP = "";
			else
				_clientIP = ip;
			
			LoaderMain.preCheckShareObjectSaveState(onLoadComplete);
		}
		
		private function progressHandlerQueue(event:LoaderEvent):void
		{
			_webPross = (event.target.progress*_everyPross*_loaderQueuePathList.length)
				
			if(_loaderQueueProgressFun != null)
				_loaderQueueProgressFun(_webPross);
		}
		
		private function completeHandlerQueue(event:LoaderEvent):void 
		{        
			var noBackAr:Array = new Array(); //没有被加载成功的路径
			var path:String = "";
			
			var ldr:* = null;
			var i:int = 0;
			var compuleteOBJ:* = null;
			
			for(i = 0;i<_loaderQueuePathList.length;i++)
			{
				path = _loaderQueuePathList[i];
				ldr = _loaderQueue.getLoader(path);
				if(ldr == null ||ldr.content == null || ldr.bytesLoaded == 0)
				{
					noBackAr.push(path);
					EngineManager.logPrint.printLog("load Try again:",path);
					continue;
				}
				switch(getloadType(path))
				{
					case LOAD_TYPE_SWF:
					case LOAD_TYPE_MAGIC:
						_loaderTempRetunList.push([getCompuleteObject(ldr,path),path,BYTE_STATE_ARRAY_WEB]);
						break;
					default:
						_loaderQueueReturnList.push([getCompuleteObject(ldr,path),path]);
						break;
				}
				EngineManager.logPrint.printLog("Webs Source:",path);
				_loaderQueue.remove(ldr);
			}
			
			
			
			
			if(noBackAr.length == 0) //加载顺利完成
			{
				checkLoadArrayOver();
			}
			else //加载失败		--重新再次去加载数据
			{
				_loaderQueuePathList = noBackAr;
				for(i = 0;i<_loaderQueuePathList.length;i++)
				{
					onloaderSource(_loaderQueue,_loaderQueuePathList[i]);
				}
				_loaderQueue.load();
			}
		}
		
		private function errorHandlerQueue(event:LoaderEvent):void 
		{     
			EngineManager.logPrint.printLog(event.target + ": " + event.text); 
		} 
		
		
		//单个文件的加载处理
		private function completeHandlerSingle(event:LoaderEvent):void 
		{      
			var ldr:* = event.target;
			var path:String = ldr.name;
			var item:LoaderItemInfo = _loaderArgDict[path];
			EngineManager.logPrint.printLog("Webs Source:",path);
			switch(getloadType(path))
			{
				case LOAD_TYPE_XML:
				case LOAD_TYPE_TEXT:
				case LOAD_TYPE_SOUND:
					doCompleteSingle(getCompuleteObject(ldr,path),path);
					break;
				default:
					handleBytesArrayData(getCompuleteObject(ldr,path),path,BYTE_STATE_SINGLE_WEB);
					break;
			}
		}   
		
		private function doCompleteSingle(OBJ:*,path:String):void
		{
			var item:LoaderItemInfo = _loaderArgDict[path];
			_loaderArgDict[path] = null;
			delete _loaderArgDict[path];
			item.callCompuleteFun(OBJ,path);
		}
		
		
		private function progressHandlerSingle(event:LoaderEvent):void
		{
			var path:String = event.target.name;
			if(_loaderSingleProgressFun != null)
				_loaderSingleProgressFun(path,event.target.progress*100);
		}
		
		//返回游戏中要用到的加载对象
		private function getCompuleteObject(ldr:*,path:String):*
		{
			var compuleteOBJ:* = ldr.content;
			switch(getloadType(path))
			{
				case LOAD_TYPE_XML:
				case LOAD_TYPE_SOUND:
				case LOAD_TYPE_TEXT:
					_cookieDict[path] = compuleteOBJ;
					break;
				case LOAD_TYPE_MAGIC:
				case LOAD_TYPE_SWF:
					LoaderMain.saveShareObjectData(path,compuleteOBJ,_versionTxt);
					break;
			}
			return compuleteOBJ;
		}
		
		//错误重新加载资源
		private function errorHandlerSingle(event:LoaderEvent):void
		{     
			EngineManager.logPrint.printLog(event.target + ": " + event.text);
			var ldr:LoaderItem = event.target as LoaderItem;
			loadOneSource(ldr.name,null,null); 
		}
		
		
		public function loadSourceArray(pathList:Array,onCompleteFun:Function,onProgressFun:Function):void
		{
			if(_loaderQueuePathList != null)
			{
				EngineManager.logPrint.printError("This is a Error on loadSourceArray, 两加载器发生冲突");
				return;
			}
			_loaderQueuePathList = new Array();
			_loaderQueueCompuleteFun = onCompleteFun;
			_loaderQueueProgressFun = onProgressFun;
			_loaderQueueReturnList = new Array();
			_loaderTempRetunList = new Array();
			
			var path:String;
			var soData:ByteArray;
			
			for(var i:int = 0;i<pathList.length;i++)
			{
				path = pathList[i];
				if(_cookieDict.hasOwnProperty(path))
				{
					_loaderQueueReturnList.push([_cookieDict[path],path]);
				}
				else
				{
					soData = LoaderMain.getShareObjectData(path,_versionTxt);
					if(soData != null)
					{
						EngineManager.logPrint.printLog("ShareObject:",path);
						_loaderTempRetunList.push([soData,path,BYTE_STATE_ARRAY_SHARE])
					}
					else
					{
						_loaderQueuePathList.push(path);
						onloaderSource(_loaderQueue,path);
					}
				}
				
			}
			
			if(_loaderQueueReturnList.length == pathList.length)
			{
				_loaderQueuePathList = null;
				if(onProgressFun != null)
					onProgressFun(100);
				onCompleteFun(_loaderQueueReturnList);
			}
			else
			{
				var totalNum:int = pathList.length - _loaderQueueReturnList.length;
				_everyPross = 100 / totalNum;
				_sharePross = 0;
				_webPross = 0;
				
				if(_loaderQueuePathList.length == 0) 
				{
					checkLoadArrayOver();
				}
				else
				{
					_loaderQueue.load();
				}
			}
		}
		
		
		public function loadOneSource(path:String,onCompleteFun:Function,onProgressFun:Function,ErrorFun:Function = null):void
		{
			
			if(_cookieDict.hasOwnProperty(path))
			{
				onCompleteFun(_cookieDict[path],path);
				return;
			}
			
			var item:LoaderItemInfo = _loaderArgDict[path];
			if(item == null)
			{
				item = new LoaderItemInfo(path);
				_loaderArgDict[path] = item;
				item.appendCompuleteFun(onCompleteFun);
			}
			else
			{
				if(onCompleteFun != null)
				{
					item.appendCompuleteFun(onCompleteFun);
					return;
				}
			}
			
			_loaderSingleProgressFun = onProgressFun;
			
			var soData:ByteArray = LoaderMain.getShareObjectData(path,_versionTxt);
			if(soData != null)
			{
				EngineManager.logPrint.printLog("ShareObject:",path);
				handleBytesArrayData(soData,path,BYTE_STATE_SINGLE_SHARE);
				return;
			}
			
			var errFun:Function = ErrorFun;
			if(errFun == null)
			{
				errFun = errorHandlerSingle;
			}
			
			switch(getloadType(path))
			{
				case LOAD_TYPE_SWF:
				case LOAD_TYPE_MAGIC:
					(new BinaryDataLoader(getVersionPath(path),{name:path,onProgress:progressHandlerSingle, onComplete:completeHandlerSingle, onError:errFun})).load();
					break;
				case LOAD_TYPE_XML:
				case LOAD_TYPE_TEXT:
					(new XMLLoader(getVersionPath(path),{name:path,onProgress:progressHandlerSingle, onComplete:completeHandlerSingle, onError:errFun})).load();
					break;
				case LOAD_TYPE_SOUND:
					(new MP3Loader(getVersionPath(path),{name:path,onProgress:progressHandlerSingle, onComplete:completeHandlerSingle, onError:errFun})).load();
					break;
				default:
					break;
			}
		}
		
		
		private function onloaderSource(loader:LoaderMax,path:String):void
		{
			switch(getloadType(path))
			{
				case LOAD_TYPE_SWF:
				case LOAD_TYPE_MAGIC:
				case LOAD_TYPE_PACKAGE:
					loader.append(new BinaryDataLoader(getVersionPath(path),{name:path}));
					break;
				case LOAD_TYPE_XML:
				case LOAD_TYPE_TEXT:
					loader.append(new XMLLoader(getVersionPath(path),{name:path}));
					break;
				case LOAD_TYPE_SOUND:
					loader.append(new MP3Loader(getVersionPath(path),{name:path}));
					break;
				default:
					break;
			}
		}
		
		
		/**
		 * 检查一个文件路径的类型
		 * @return 类型请参考 GameLoader; 
		 */
		public function getloadType(path:String):int
		{
			var tempStr:String = path.toLocaleUpperCase();
			if(tempStr.lastIndexOf(".SWF") != -1)
				return LOAD_TYPE_SWF;
			else if(tempStr.lastIndexOf(".PNG") != -1)
				return LOAD_TYPE_MAGIC;
			else if(tempStr.lastIndexOf(".JPG") != -1)
				return LOAD_TYPE_MAGIC;
			else if(tempStr.lastIndexOf(".XML") != -1)
				return LOAD_TYPE_XML;
			else if(tempStr.lastIndexOf(".TXT") != -1)
				return LOAD_TYPE_TEXT;
			else if(tempStr.lastIndexOf(".MP3") != -1)
				return LOAD_TYPE_SOUND;
			else if(tempStr.lastIndexOf(".PAK") != -1)
				return LOAD_TYPE_PACKAGE;
			return LOAD_TYPE_TEXT; 
		}
		
		/**
		 * 设置XML打包的数据,以保证后期XML的加载速度
		 */
		public function setXMLDataCookie(data:ByteArray):void
		{
			var zipfile:ZipFile = new ZipFile(data);
			var entry:ZipEntry;
			var path:String;
			for(var i:int = 0;i<zipfile.entries.length;i++)
			{
				entry = zipfile.entries[i];
				path = "config/"+entry.name;
				if(path.toLocaleUpperCase().lastIndexOf(".XML") != -1)
				{
					try
					{
						_cookieDict[path] = new XML((zipfile.getInput(entry).toString()));
					}
					catch(e:Error)
					{
						EngineManager.logPrint.printLog("load XML Error:"+path,e.toString());
					}
				}
			}
		}
		
		
		private function getVersionPath(path:String):String
		{
			if(_versionTxt != VERSION_NO)
			{
				path = path.replace(".swf",_versionTxt+".swf");
				path = path.replace(".png",_versionTxt+".png"); 
				path = path.replace(".txt",_versionTxt+".txt");
				path = path.replace(".xml",_versionTxt+".xml");
				path = path.replace(".jpg",_versionTxt+".jpg");
				path = path.replace(".pak",_versionTxt+".pak");
				//path = path.replace(".mp3",_versionTxt+".mp3");
			}
			
			path = _clientIP + path;
			EngineManager.logPrint.printLog("load Path:"+path);
			return path;
		}
		
		
		/**
		 * 检查加载阵列是否加载完成
		 */
		private function checkLoadArrayOver():void
		{
			if(_loaderTempRetunList.length == 0)
			{
				_loaderQueuePathList = null;
				_loaderQueueCompuleteFun(_loaderQueueReturnList);
			}
			else
			{
				var ar:Array = _loaderTempRetunList.shift();
				handleBytesArrayData(ar[0],ar[1],ar[2]);
			}
		}
		
		/**
		 * 所有图片,以及SWF前置通过二进制加载,然后再对二进度进行转换加载生成SWF和图片.
		 */
		private function handleBytesArrayData(bytes:ByteArray,path:String,byteState:int):void
		{
			var bytesLoader:Loader = new Loader();
			var context:LoaderContext = new LoaderContext(false);
			context.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
			bytesLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadBytesComplete);
			bytesLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,loadBytesProgress);
			bytesLoader.loadBytes(bytes,context);
			
			function loadBytesComplete(evt:Event):void
			{
				bytesLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadBytesComplete);
				var compuleteOBJ:* = null;
				if(getloadType(path) == LOAD_TYPE_MAGIC)
				{
					compuleteOBJ = (bytesLoader.content as Bitmap).bitmapData;
					
				}
				else
				{
					compuleteOBJ = new MySWFLoader(bytesLoader);
				}
				if(byteState == BYTE_STATE_ARRAY_SHARE)
				{
					_sharePross = _sharePross + _everyPross;
				}
				_loadBytesComplete(compuleteOBJ,path,byteState);
				
			}
			
			function loadBytesProgress(evt:ProgressEvent):void
			{
				if(byteState == BYTE_STATE_SINGLE_SHARE)
				{
					_loaderSingleProgressFun(path,(evt.bytesLoaded / evt.bytesTotal)* 100);
				}
				else if(byteState == BYTE_STATE_ARRAY_SHARE)
				{
					_loaderQueueProgressFun(_sharePross + (evt.bytesLoaded / evt.bytesTotal) * _everyPross + _webPross,path)
				}
			}
			
			
		}
		
		/**
		 * 为避免异步出错,放到成员函数再处理数据,并做缓存处理
		 */
		private function _loadBytesComplete(compuleteOBJ:*,path:String,byteState:int):void
		{
			_cookieDict[path] = compuleteOBJ;
			if(byteState == BYTE_STATE_SINGLE_SHARE || byteState == BYTE_STATE_SINGLE_WEB)
			{
				doCompleteSingle(compuleteOBJ,path);
			}
			else
			{
				_loaderQueueReturnList.push([compuleteOBJ,path]);
				checkLoadArrayOver();
			}
		}
		
	}
}